home *** CD-ROM | disk | FTP | other *** search
- /*
- * eval --- evaluate expression
- *
- * an expression is constructed like this:
- *
- * expr ::= expr + term |
- * expr - term ;
- * expr * term ;
- * expr / term ;
- * expr | term ;
- * expr & term ;
- * expr % term ;
- * expr ^ term ;
- *
- * term ::= symbol |
- * * |
- * constant ;
- *
- * symbol ::= string of alphanumerics with non-initial digit
- *
- * constant ::= hex constant |
- * binary constant |
- * octal constant |
- * decimal constant |
- * ascii constant;
- *
- * hex constant ::= '$' {hex digits};
- *
- * octal constant ::= '@' {octal digits};
- *
- * binary constant ::= '%' { 1 | 0 };
- *
- * decimal constant ::= {decimal digits};
- *
- * ascii constant ::= ''' any printing char;
- *
- */
- eval()
- {
- int left,right; /* left and right terms for expression */
- char o; /* operator character */
-
- #ifdef DEBUG
- printf("Evaluating %s\n",Optr);
- #endif
- Force_byte = NO;
- Force_word = NO;
- if(*Optr=='<'){
- Force_byte++;
- Optr++;
- }
- else if(*Optr=='>'){
- Force_word++;
- Optr++;
- }
- left = get_term(); /* pickup first part of expression */
-
- while( is_op(*Optr)){
- o = *Optr++; /* pickup connector and skip */
- right = get_term(); /* pickup current rightmost side */
- switch(o){
- case '+': left += right; break;
- case '-': left -= right; break;
- case '*': left *= right; break;
- case '/': left /= right; break;
- case '|': left |= right; break;
- case '&': left &= right; break;
- case '%': left %= right; break;
- case '^': left = left^right; break;
- }
- }
-
- Result= left;
- #ifdef DEBUG
- printf("Result=%x\n",Result);
- printf("Force_byte=%d Force_word=%d\n",Force_byte,Force_word);
- #endif
- return(YES);
- }
-
- /*
- * is_op --- is character an expression operator?
- */
- is_op(c)
- char c;
- {
- if( any(c,"+-*/&%|^"))
- return(YES);
- return(NO);
- }
-
-
- /*
- * get_term --- evaluate a single item in an expression
- */
- get_term()
- {
- char hold[MAXBUF];
- char *tmp;
- int val = 0; /* local value being built */
- int minus; /* unary minus flag */
- struct nlist *lookup(),*pointer;
- struct link *pnt,*bpnt;
-
- if( *Optr == '-' ){
- Optr++;
- minus =YES;
- }
- else
- minus = NO;
-
- while( *Optr == '#' ) Optr++;
-
- /* look at rest of expression */
-
- if(*Optr=='%'){ /* binary constant */
- Optr++;
- while( any(*Optr,"01"))
- val = (val * 2) + ( (*Optr++)-'0');
- }
- else if(*Optr=='@'){ /* octal constant */
- Optr++;
- while( any(*Optr,"01234567"))
- val = (val * 8) + ((*Optr++)-'0');
- }
- else if(*Optr=='$'){ /* hex constant */
- Optr++;
- while( any(*Optr,"0123456789abcdefABCDEF"))
- if( *Optr > '9' )
- val = (val * 16) + 10 + (mapdn(*Optr++)-'a');
- else
- val = (val * 16) + ((*Optr++)-'0');
- }
- else if( any(*Optr,"0123456789")){ /* decimal constant */
- while(*Optr >= '0' && *Optr <= '9')
- val = (val * 10) + ( (*Optr++)-'0');
- }
- else if(*Optr=='*'){ /* current location counter */
- Optr++;
- val = Old_pc;
- }
- else if(*Optr=='\''){ /* character literal */
- Optr++;
- if(*Optr == EOS)
- val = 0;
- else
- val = *Optr++;
- }
- else if( alpha(*Optr) ){ /* a symbol */
- tmp = hold; /* collect symbol name */
- while(alphan(*Optr))
- *tmp++ = *Optr++;
- *tmp = EOS;
- pointer = lookup(hold);
- if (pointer != NULL)
- {
- if (Pass == 2)
- {
- pnt = pointer->L_list;
- bpnt = NULL;
- while (pnt != NULL)
- {
- bpnt = pnt;
- pnt = pnt->next;
- }
- pnt = (struct link *) alloc(sizeof(struct link));
- if (bpnt == NULL)
- pointer->L_list = pnt;
- else bpnt->next = pnt;
- pnt->L_num = Line_num;
- pnt->next = NULL;
- }
- val = Last_sym;
- }
- else{
- if(Pass==1){ /* forward ref here */
- fwdmark();
- if( !Force_byte )
- Force_word++;
- val = 0;
- }
- }
- if(Pass==2 && Line_num==F_ref && Cfn==Ffn){
- if( !Force_byte )
- Force_word++;
- fwdnext();
- }
- }
- else
- /* none of the above */
- val = 0;
-
- if(minus)
- return(-val);
- else
- return(val);
- }
-